Children’s rights and development are critical to building a nation’s future.
This report leverages UNICEF’s data to highlight key indicators across countries, focusing on:
Health outcomes
Educational progress
Nutritional status
Child protection measures
Our goal is to uncover meaningful trends that can guide effective, data-driven interventions.
Data Exploration Journey
To better understand how children’s well-being varies across the world,
we explore the available UNICEF indicators through a series of visualizations.
We start by examining which countries stand out based on their average observed values.
Then, we trace the evolution of these values over time, highlighting differences between males and females.
Finally, we zoom out to a global perspective with a colorful world map showing the latest data across nations.
These visual insights help reveal both progress and persistent challenges in child development across regions.
Code
# Import librariesimport plotly.express as pximport plotly.graph_objects as goimport pandas as pdfrom plotnine import*import matplotlib.pyplot as pltimport seaborn as sns# Load datasetdf = pd.read_csv("unicef_indicator_2.csv")# Clean: Group by country and take the mean (or max) observed valuedf_clean = ( df.groupby('country', as_index=False) .agg({'obs_value':'mean'}))# Sort and select top 10 countriestop10 = df_clean.sort_values(by='obs_value', ascending=False).head(10)# For pie chart, calculate top 5top5 = df.sort_values(by='obs_value', ascending=False).head(5)# Display first few rowsdf.head()# Table of Top 10 Countriestop10 = top10.reset_index(drop=True)top10.index = top10.index +1top10
country
obs_value
1
Ethiopia
44.833333
2
Burkina Faso
41.500000
3
Chad
39.033333
4
Cameroon
38.900000
5
Togo
38.466667
6
Madagascar
36.700000
7
Haiti
35.233333
8
Niger
34.333333
9
Nigeria
31.500000
10
Burundi
30.933333
Focusing on the Leaders
To identify which countries have the highest average outcomes,
we visualize the Top 10 countries based on their observed values.
This helps highlight regions making significant progress in key child development indicators.
Summary of Average Observed Values by Country
The table below displays the average observed values across countries, providing a snapshot of key performers.
Identifying countries with the highest averages enables targeted focus for deeper analysis.
Interactive Visualization of Top 10 Countries
Code
fig = px.bar( top10, x='obs_value', y='country', orientation='h', text='obs_value', color='obs_value', color_continuous_scale='Blues', title="Top 10 Countries by Observed Value (Interactive)"# Simple string here)fig.update_layout( title={'text': "Top 10 Countries by Observed Value",'x': 0.5,'xanchor': 'center','font': {'size': 24} }, margin=dict(t=100), xaxis_title='Observed Value', yaxis_title='Country', plot_bgcolor='white')fig.update_traces( texttemplate='%{text:.1f}', textposition='outside')fig.show()
Understanding Trends Over Time
Beyond averages, it’s crucial to explore how countries have evolved over time.
In the next visualization, we track the observed values across different periods, separated by gender,
to spot improvements, declines, or emerging patterns in children’s well-being.
Observed Values Over Time
To understand how progress unfolds over time, we plot observed values across different years, separated by sex.
This view highlights patterns, fluctuations, and trends that reveal the trajectory of child development indicators globally.
Code
# 1. Prepare Figurefig = go.Figure()# 2. Loop through each country and add Male and Female separatelyfor country in df['country'].unique(): df_country = df[df['country'] == country]for sex, color inzip(['Male', 'Female'], ['blue', 'red']): # Male in blue, Female in red df_sex = df_country[df_country['sex'] == sex] fig.add_trace(go.Scatter( x=df_sex['time_period'], y=df_sex['obs_value'], mode='lines+markers', # <-- Keep lines + points name=f"{country} - {sex}", line_shape="spline", # <-- Smooth curves line=dict(color=color, width=2), # <-- Make lines slightly thicker opacity=0.4# <-- Light opacity to reduce clutter ))# 3. Update Layoutfig.update_layout( title={'text': "Observed Values Over Time: Male vs Female Across Countries",'x':0.5,'xanchor': 'center','font': dict(size=24) }, xaxis_title="Time Period", yaxis_title="Observed Value", template="plotly_white", hovermode="x unified", legend_title="Country - Sex", height=700, margin=dict(t=100, l=50, r=50, b=50),)# 4. Show figurefig.show()
Deep Dive into Specific Countries
While general trends are useful, it’s also important to focus on particular countries individually.
Here, we zoom into selected countries to better understand their unique journeys.
A scatter plot with a linear regression line helps highlight the overall direction of change — whether progress is accelerating, slowing down, or remaining steady.
Trend of Observed Values by Country
Beyond static averages, it’s essential to explore temporal trends at the country level.
The scatter plot below includes a fitted regression line to summarize the overall trend across selected countries.
Code
# 📌 First: Filter your DataFrame for specific countriesselected_countries = ["Cameroon", "Ethiopia", "Haiti", "Nigeria"]df_filtered = df[df['country'].isin(selected_countries)]# 📌 Second: Create the scatter plot with a regression lineimport plotly.express as pxfig = px.scatter( df_filtered, x="time_period", y="obs_value", color="country", trendline="ols", # Add ordinary least squares regression trendline_scope="overall", # Single regression line for all data title="Scatter Plot with Linear Regression Line", labels={"time_period": "Time Period","obs_value": "Observed Value","country": "Country" }, template="plotly_white")# 📌 Third: Beautify the chart layoutfig.update_layout( title={'text': "Scatter Plot with Linear Regression Line (Combined)",'x': 0.5,'xanchor': 'center','font': dict(size=24) }, height=600, legend_title="Country", margin=dict(t=80, l=50, r=50, b=50),)# 📌 Fourth: Show the final figurefig.show()
Global Overview of Observed Values
After exploring individual country trends, it’s valuable to step back and look at the bigger picture.
The following world map presents the latest observed value for each available country.
This visualization helps identify regional disparities, highlight clusters of progress, and spot areas where targeted interventions might be most needed.
Code
# Take the latest value for each country (even if years differ)df_latest = df.sort_values('time_period').groupby('country').tail(1)fig = go.Figure(data=go.Choropleth( locations=df_latest['country'], locationmode='country names', z=df_latest['obs_value'], colorscale='Viridis', colorbar_title='Observed Value', marker_line_color='white', marker_line_width=0.5,))fig.update_layout( title_text='World Map of Observed Value (Latest Available per Country)', title_x=0.5, geo=dict( showframe=False, showcoastlines=True, coastlinecolor="white", showland=True, landcolor="rgb(217, 217, 217)", oceancolor="rgb(173, 216, 230)", showocean=True, projection_type='natural earth' ), template="plotly_white", margin=dict(t=50, l=0, r=0, b=0),)fig.show()
Animated Rotating Pie Chart of Top 10 Countries by Observed Value
This visualization presents an interactive and animated pie chart displaying the top 10 countries based on their observed values.
Built using Plotly, the chart starts with a static view and offers a “Play” button to trigger a smooth 360-degree rotation animation.
Each frame of the animation gradually rotates the pie chart, providing a dynamic and engaging way to explore the distribution of values among the countries.
The chart also features a clean design with a slight hole in the center (creating a donut chart effect) and a clear title to enhance readability.
Code
import numpy as nplabels = top10['country']values = top10['obs_value']fig = go.Figure()# Add the initial pie chartfig.add_trace( go.Pie(labels=labels, values=values, hole=0.3, rotation=0))# Create 30 frames rotating the chartfig.frames = [ go.Frame( data=[go.Pie(labels=labels, values=values, hole=0.3, rotation=angle)], name=str(angle) )for angle in np.linspace(0, 360, 30)]# Add play button for animationfig.update_layout( title_text="Top 10 Countries by Observed Value", title_font_size=24, updatemenus=[{"type": "buttons","buttons": [{"label": "Play","method": "animate","args": [None, {"frame": {"duration": 100, "redraw": True}, "fromcurrent": True}] }] }], margin=dict(t=100, b=50),)fig.show()
Conclusion
This report provides an analytical overview of key child development indicators across countries, using UNICEF’s valuable dataset.
Through interactive visualizations, we identified both high-performing regions and areas needing urgent intervention.
Future efforts should focus on sustaining gains, closing regional gaps, and ensuring that no child is left behind.